package com.daffodil.easyfile.controller;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.daffodil.core.annotation.Log;
import com.daffodil.core.annotation.Log.BusinessType;
import com.daffodil.core.controller.BaseController;
import com.daffodil.core.entity.JsonResult;
import com.daffodil.core.entity.Page;
import com.daffodil.core.entity.TableInfo;
import com.daffodil.easyfile.config.EasyfileConfig;
import com.daffodil.easyfile.entity.EasyfileChunk;
import com.daffodil.easyfile.entity.EasyfileEntity;
import com.daffodil.easyfile.service.IEasyfileService;
import com.daffodil.util.JacksonUtils;
import com.daffodil.util.ServletUtils;
import com.daffodil.util.StringUtils;
import com.daffodil.util.file.FileUtils;
import com.daffodil.util.text.Convert;

/**
 * Easyfile文件存储管理服务
 * @author yweijian
 * @date 2020年12月22日
 * @version 1.0
 * @description
 */
@Controller
@RequestMapping("/easyfile")
public class EasyfileController extends BaseController {
	
	private static final Logger log = LoggerFactory.getLogger(EasyfileController.class);
	
	private String prefix = "easyfile";
	
	@Value("${spring.servlet.upload.file-path}")
	private String uploadFilePath;
	
	@Autowired
	private EasyfileConfig easyfileConfig;
	
	@Autowired
	private IEasyfileService easyfileService;

	@RequiresPermissions("easyfile:file:view")
	@GetMapping()
	public String easyfile() {
		return prefix + "/easyfile";
	}
	
	@SuppressWarnings("unchecked")
	@RequiresPermissions("easyfile:file:list")
	@GetMapping("/list")
	@ResponseBody
	public TableInfo list(EasyfileEntity easyfileEntity) {
		initQuery(easyfileEntity, new Page());
		List<EasyfileEntity> list = easyfileService.selectEasyfileEntityList(query);
		return initTableInfo(list, query);
	}
	
	/**
	 * 获取所有上传文件配置
	 * @return
	 */
	@GetMapping("/config")
	@ResponseBody
	public JsonResult config() {
		return JsonResult.success(easyfileConfig);
	}
	
	/**
	 * 上传页面
	 * @return
	 */
	@GetMapping("/upload/{business}")
	@RequiresPermissions("easyfile:file:upload")
	public String upload(@PathVariable("business") String business, ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) {
		
		Map<String, Object> allowConfig = easyfileConfig.getEasyfileConfigByBusiness(business);
		// 如果是Ajax请求，返回Json字符串。
		if (ServletUtils.isAjaxRequest(request)) {
			JsonResult jsonResult = JsonResult.success(allowConfig);
			return ServletUtils.renderString(response, JacksonUtils.toJSONString(jsonResult));
		}
		
		modelMap.put("allowConfig", allowConfig);
		return prefix + "/upload";
	}
	
	/**
	 * 上传
	 * @param file
	 * @param easyfileChunk
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/upload")
	@RequiresPermissions("easyfile:file:upload")
	@Log(title = "文件管理", businessType = BusinessType.UPLOAD)
	@ResponseBody
	public JsonResult upload(@RequestParam("file") MultipartFile file, EasyfileChunk easyfileChunk) throws Exception {
		easyfileChunk = easyfileService.easyfileUpload(file, easyfileChunk, uploadFilePath);
		if((easyfileChunk.getChunk() + 1) == easyfileChunk.getChunks()) {//当最后一个分片上传成功后要执行文件合并
			EasyfileEntity easyfileEntity = easyfileService.easyfileMerge(easyfileChunk, uploadFilePath);
			if(StringUtils.isNull(easyfileEntity)) {
				easyfileService.removeEasyfileChunk(easyfileChunk);
				return JsonResult.error("文件合并失败", easyfileChunk);
			}else {
				return JsonResult.success(easyfileEntity);
			}
		}
		return JsonResult.success(easyfileChunk);
	}
	
	/**
	 * 下载
	 * @param fileName
	 * @param delete
	 * @param response
	 * @param request
	 */
	@GetMapping("/download/{id}")
	@RequiresPermissions("easyfile:file:download")
	@Log(title = "文件管理", businessType = BusinessType.DOWNLOAD)
	@ResponseBody
	public void download(@PathVariable("id") String id, HttpServletResponse response, HttpServletRequest request) {
		try {
			EasyfileEntity easyfileEntity = easyfileService.selectEasyfileEntityById(id);
			String filePath = uploadFilePath + File.separator + easyfileEntity.getFilePath();
			String fileName = FileUtils.setFileDownloadHeader(request, easyfileEntity.getOriginalName());
			response.setCharacterEncoding("utf-8");
			response.setContentType("multipart/form-data");
			response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
			FileUtils.writeBytes(filePath, response.getOutputStream());
		} catch (Exception e) {
			log.error("下载文件失败", e);
		}
	}
	
	/**
	 * 删除文件信息
	 * @param ids
	 * @return
	 */
	@RequiresPermissions("easyfile:file:remove")
	@Log(title = "文件管理", businessType = BusinessType.DELETE)
	@PostMapping("/remove")
	@ResponseBody
	public JsonResult remove(String ids) {
		easyfileService.deleteEasyfileEntityByIds(Convert.toStrArray(ids));
		return JsonResult.success();
	}
	
	/**
	 * 预览文件（一般是图片和PDF，其他文件无法在浏览器中预览）
	 * @param filename
	 * @param response
	 */
	@GetMapping("/view/{id}")
	public void view(@PathVariable("id") String id, HttpServletResponse response){
		try {
			EasyfileEntity easyfileEntity = easyfileService.selectEasyfileEntityById(id);
			if(easyfileEntity != null) {
				String filePath = uploadFilePath + File.separator + easyfileEntity.getFilePath();
				FileUtils.writeBytes(filePath, response.getOutputStream());
			}
		} catch (IOException e) {
			log.error("预览文件失败", e);
		}
	}
	
}
